iOS/Android tablet의 MonitorScreen은 오버레이와 색상으로 정보를 압축한다. 두 가지 모두 e-ink에서 비싸다. 화면을 통일하려는 시도는 결국 같은 4가지 충돌을 만든다.
반투명 HUD 패널은 LCD에서 자연스럽지만, EPD에서는 alpha 합성이 부분 갱신과 결합되며 잔상을 누적시킨다. GC16 full refresh로 지우는 순간 사용자는 200–500ms의 검은 깜박임을 본다.
B&W 16-grey, Kaleido 3 4096-color는 LCD 채도와 다르다. 빨강=거부, 초록=승인 같은 순수 색 의존 코드는 색약 사용자뿐 아니라 e-ink에서도 무너진다. 글리프와 텍스트가 권위를 가져야 한다.
tablet HUD는 12sp 라벨이 흔하다. e-ink는 dither 한계 + 저대비로 작은 글자가 무너진다. “같은 픽셀 위치”를 강제하면 정보가 가독성에 양보된다.
크리처 애니메이션은 A2(10fps), 게이지는 DU(2s), 세션 패널은 거의 정적이다. 이를 한 레이어에서 그리면 가장 빠른 zone의 잔상이 가장 느린 zone으로 번진다.
MonitorScreen과 EinkMonitorScreen이 같은 외형을 흉내내려 할수록 공유 코드가 줄어든다. e-ink는 자기 형태를 가진 viewer일 때 가장 적은 코드로 정확하다.
Rockchip EinkManager, Onyx BaseDevice, KOReader RK35xxEPDController — refresh mode 호출 표면이 셋이다. UI가 직접 호출하면 디바이스 분기가 UI 코드로 새어 나온다.
네 가지 원칙을 코드 경계로 강제한다. 이것이 깨지는 코드 변경은 review에서 reject한다.
DashboardState · FocusAction · AttentionRequest는 공통. 레이아웃은 surface마다 자유.
반투명 오버레이 금지. 화면은 명시적 zone으로만 분할. 각 zone은 자기 refresh policy를 갖는다.
승인/거부/대기/연결 모두 글리프와 라벨로 1차 표현. 색은 color e-ink에서 추가 강조용일 뿐.
UI는 EpdRefreshController만 호출. Rockchip/Onyx/Kobo/Color 분기는 driver 모듈 내부에 갇혀 있다.
| Zone | Refresh | 역할 |
|---|---|---|
| CHROME | DU · 2 s | 로고, 세션 목록, settings 진입. 거의 안 변함. |
| FOCUS | A2 · 200 ms | 현재 선택한 세션의 model · state · project. |
| TERRARIUM | A2/anim · 10 fps | 크리처 애니메이션. 상태 전환에서만 GC16 cleanup. |
| GAUGES | DU · 2 s | 5h/7d 게이지, OAuth/Ollama 모델 카탈로그. |
| TIMELINE | A2 · 300 ms | 이벤트 로그. append-only이므로 부분 갱신 친화적. |
| ATTENTION | GC16 once | awaiting_* 진입 시 한 번 full refresh, 답변 옵션 명료화. |
각 zone은 RefreshHint를 emit하고 EpdRefreshController가 디바이스별로 번역한다. UI 코드는 벤더 분기 0줄.
16-grey · landscape 1404×1872 dp 등가 · GC16 + DU + A2 혼합
4096 색 · A2 animation mode · 같은 레이아웃, 의미 매핑은 색을 강조로만 사용. B&W 화면을 그대로 켰을 때 정보가 손실되지 않는 것이 ground truth.
// EinkAquariumFrame.kt — 현재 형태 if (manufacturer == "rockchip") { einkManager.setMode("12") // A2 einkManager.sendOneFullFrame() } else if (manufacturer == "onyx") { device.setViewDefaultUpdateMode(A2_MODE) } else if (isColorEink) { // skip dither, use animation mode ... }
UI 컴포넌트가 디바이스 SPI를 직접 부른다. 새 e-ink 기기 추가 = UI 코드 수정.
// EinkMonitorScreen.kt EinkZone(id = "terrarium", hint = RefreshHint.Anim(fps = 10)) { TerrariumProjection(state) } EinkZone(id = "attention", hint = RefreshHint.FullOnce) { AttentionProjection(state.attention) } // EpdRefreshController.kt — driver port interface EpdRefreshController { fun apply(zone: ZoneId, hint: RefreshHint) } // RockchipEpdDriver · OnyxEpdDriver · ColorKaleidoDriver // 새 기기 추가 = driver 한 파일 추가
| 레이어 | LCD/LED와 공유? | 위치 | 설명 |
|---|---|---|---|
| DashboardState · FocusAction · AttentionRequest | SHARED | shared/state-model | WS 프로토콜에서 직접 derived. 모든 surface가 같은 store를 읽는다. |
| Creature sprite paths · Timeline parser | SHARED | shared/render | SVG path → Compose path / Canvas drawRect fallback. 한 source. |
| Layout · zones · refresh hints | EINK ONLY | ui/eink/projection | tablet/iOS와 모양이 달라야 한다. 흉내내지 않는다. |
| EpdRefreshController · vendor drivers | EINK ONLY | ui/eink/epd | Rockchip · Onyx · Kaleido 분기는 여기서 끝난다. UI는 모른다. |
| Color palette · glyph table | SHARED w/ fallback | shared/tokens | 같은 의미 키, B&W 매핑 + color e-ink 매핑이 한 테이블에 있음. |
현재 EinkRenderer·EinkAnimatedRefreshZone 안에 흩어진 벤더 호출을 driver port로 모은다. UI 변경 없음. 위험 낮음.
공통 wrapper로 zone을 감싼다. 기존 EinkMonitorScreen의 5 영역을 순차적으로 zone으로 마이그레이션. 화면은 그대로.
오버레이를 모두 slot으로 변환. Attention zone을 GC16 once 정책으로 도입. Crema/Pantone QA를 같이 돌려 잔상 회귀 확인.
색에만 의존하는 state 표현 제거. Settings에서 “색 강조 끄기” 토글로 회귀 테스트.
Kaleido 3에서만 활성화되는 token override layer. B&W 화면을 켜면 자동으로 빠진다.
Onyx · Kobo 드라이버 추가. 각 1 PR. UI/projection 변경 없이 새 디바이스 지원.